/*
 * @(#) SPCChart.java 2013-8-2 上午10:43:52
 *
 * Copyright 2013 Rockwell Automation, Inc. All rights reserved.
 * Rockwell Automation PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */package com.osi.mes.base.control;

import java.awt.Color;
import java.awt.Dimension;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Vector;

import com.datasweep.compatibility.client.ATRow;
import com.datasweep.compatibility.client.ATRowFilter;
import com.datasweep.compatibility.client.DCInstance;
import com.datasweep.compatibility.client.DCInstanceFilter;
import com.datasweep.compatibility.client.Response;
import com.datasweep.compatibility.ui.BorderStyle;
import com.datasweep.compatibility.ui.DateTimePicker;
import com.datasweep.compatibility.ui.DateTimePickerFormat;
import com.datasweep.compatibility.ui.FlatButton;
import com.datasweep.compatibility.ui.FlatLabel;
import com.datasweep.compatibility.ui.LayoutStyle;
import com.datasweep.compatibility.ui.Panel;
import com.datasweep.compatibility.ui.TabControl;
import com.datasweep.compatibility.ui.TabPage;
import com.datasweep.compatibility.ui.Time;
import com.datasweep.compatibility.ui.chart.DsChart;
import com.datasweep.compatibility.ui.chart.DsStyle;
import com.datasweep.compatibility.ui.grid.DsGrid;
import com.datasweep.plantops.common.constants.filtering.IDCSInstanceFilterAttributes;
import com.datasweep.plantops.common.constants.filtering.IFilterSortOrders;
import com.datasweep.plantops.swing.ControlDock;
import com.ibm.icu.text.SimpleDateFormat;
import com.osi.mes.base.control.BaseUIActivity;
import com.osi.mes.base.util.StdStats;
import com.osi.mes.pm.TestConnectQLight;
import com.rockwell.activity.CComponentEvent;
import com.rockwell.activity.CComponentEventListener;
import com.rockwell.activity.ItemDescriptor;

/**
 * SPC图表
 * 
 * @author Nemo, 2013-8-2 上午10:47:44
 */
public class SPCChart extends BaseUIActivity implements CComponentEventListener
{

	private Panel panel;

	private Panel panelUp;

	private Panel panelTop;

	private Panel panelTopTop;

	private Panel panelContent;

	private Panel panelGrids;

	private Panel panelGridData;

	private Panel pnaleGridAnalysis;

	private TabControl tabControl;

	private TabPage tabPageChartData;

	private TabPage tabPageChartRange;

	private DateTimePicker dateTimePickerStart;

	private DateTimePicker dateTimePickerEnd;

	private FlatLabel label;

	private FlatButton buttonQuery;

	private DsChart dsChartAvg;

	private DsChart dsChartRange;

	private DsGrid dsGridData;

	private DsGrid dsGridAnalysis;

	private boolean isAlert;

	public boolean isAlert()
	{
		return isAlert;
	}

	public void setAlert(boolean isAlert)
	{
		this.isAlert = isAlert;
	}

	public SPCChart()
	{
		super();
		initGUI();
	}

	/**
	 * 初始化界面
	 */
	private void initGUI()
	{
		// this.setPreferredSize(new Dimension(645,315));
		this.setDock(ControlDock.FILL);
		panel = createPanel(
			"spcPanel", ControlDock.FILL);
		this.add(panel);

		panelUp = createPanel(
			"panelUp", ControlDock.TOP, 645, 135);
		panelUp.setLayoutStyle(LayoutStyle.DOCK_AND_ANCHOR);
		panel.add(panelUp);

		panelTopTop = createPanel(
			"spcPanelTopTop", ControlDock.LEFT, 500, 150);
		panelTopTop.setLayoutStyle(LayoutStyle.DOCK_AND_ANCHOR);
		panelUp.add(panelTopTop);

		panelTop = createPanel(
			"spcPanelTop", ControlDock.TOP, 100, 45);
		panelTop.setLayoutStyle(LayoutStyle.FLOW);
		panelTopTop.add(panelTop);

		panelContent = createPanel(
			"spcPanelContect", ControlDock.FILL);
		panel.add(panelContent);

		dateTimePickerStart = createDateTimePicker("spcTimeStart");
		dateTimePickerStart.setFormat(DateTimePickerFormat.CUSTOM);
		dateTimePickerStart.setCustomFormat("yyyy-MM-dd HH:mm:ss");
		dateTimePickerStart.addCComponentEventListener(this);

		label = new FlatLabel();
		label.setName("spcLabel");
		label.setText("--");
		label.setPreferredSize(new Dimension(20, 35));

		dateTimePickerEnd = createDateTimePicker("spcTimeEnd");
		dateTimePickerEnd.setFormat(DateTimePickerFormat.CUSTOM);
		dateTimePickerEnd.setCustomFormat("yyyy-MM-dd HH:mm:ss");
		dateTimePickerEnd.addCComponentEventListener(this);

		buttonQuery = new FlatButton();
		buttonQuery.setName("buttonQuery");
		buttonQuery.setText("查询");
		buttonQuery.setPreferredSize(new Dimension(100, 30));
		buttonQuery.addCComponentEventListener(this);

		panelTop.add(dateTimePickerStart);
		panelTop.add(label);
		panelTop.add(dateTimePickerEnd);
		panelTop.add(buttonQuery);

		tabControl = createTabControl("tabControl");
		panelContent.add(tabControl);

		tabPageChartData = createTabPage("tabPageChartData");
		tabPageChartData.setText("X-Bar");
		tabControl.add(tabPageChartData);

		tabPageChartRange = createTabPage("tabPageChartRange");
		tabPageChartRange.setText("Range");
		tabControl.add(tabPageChartRange);

		panelGridData = createPanel(
			"panelGridData", ControlDock.FILL, 490, 105);
		panelGridData.setLayoutStyle(LayoutStyle.DOCK_AND_ANCHOR);
		panelGridData.setBorderStyle(BorderStyle.FIXED_SINGLE);
		panelTopTop.add(panelGridData);

		pnaleGridAnalysis = createPanel(
			"pnaleGridAnalysis", ControlDock.RIGHT, 125, 108);
		pnaleGridAnalysis.setLayoutStyle(LayoutStyle.DOCK_AND_ANCHOR);
		pnaleGridAnalysis.setBorderStyle(BorderStyle.FIXED_SINGLE);
		panelUp.add(pnaleGridAnalysis);

		dsGridData = new DsGrid();
		dsGridData.setName("dsGridData");
		dsGridData.setNumberOfColumns(2);
		dsGridData.setNumberOfRows(5);
		dsGridData.setHeaderHeight(0);
		dsGridData.setRowHeight(17);
		dsGridData.setCellText(
			0, 0, "Time");
		dsGridData.setCellText(
			1, 0, "Average");
		dsGridData.setCellText(
			2, 0, "R");
		dsGridData.setCellText(
			3, 0, "Point Value");
		dsGridData.setCellText(
			4, 0, "Cumnlative Score");
		dsGridData.setDock(ControlDock.FILL);
		panelGridData.add(dsGridData);

		dsGridAnalysis = new DsGrid();
		dsGridAnalysis.setName("dsGridAnalysis");
		dsGridAnalysis.setNumberOfColumns(2);
		dsGridAnalysis.setNumberOfRows(10);
		dsGridAnalysis.setHeaderHeight(0);
		dsGridAnalysis.setRowHeight(13);
		dsGridAnalysis.setColumnWidth(60);
		dsGridAnalysis.setDock(ControlDock.FILL);
		dsGridAnalysis.setCellText(
			0, 0, "Avg");
		dsGridAnalysis.setCellText(
			1, 0, "High%");
		dsGridAnalysis.setCellText(
			2, 0, "Low%");
		dsGridAnalysis.setCellText(
			3, 0, "CPK");
		dsGridAnalysis.setCellText(
			4, 0, "UCL");
		dsGridAnalysis.setCellText(
			5, 0, "LCL");
		dsGridAnalysis.setCellText(
			6, 0, "Deviation");
		dsGridAnalysis.setCellText(
			7, 0, "No.tests");
		dsGridAnalysis.setCellText(
			8, 0, "Max");
		dsGridAnalysis.setCellText(
			9, 0, "Min");
		dsGridAnalysis.setCellValue(
			0, 1, 0.00);
		dsGridAnalysis.setCellValue(
			1, 1, "0.00%");
		dsGridAnalysis.setCellValue(
			2, 1, "0.00%");
		dsGridAnalysis.setCellValue(
			3, 1, 0.00);
		dsGridAnalysis.setCellValue(
			4, 1, 0.00);
		dsGridAnalysis.setCellValue(
			5, 1, 0.00);
		dsGridAnalysis.setCellValue(
			6, 1, 0.00);
		dsGridAnalysis.setCellValue(
			7, 1, 0);
		dsGridAnalysis.setCellValue(
			8, 1, 0.00);
		dsGridAnalysis.setCellValue(
			9, 1, 0.00);
		pnaleGridAnalysis.add(dsGridAnalysis);

		dsChartAvg = new DsChart();
		dsChartAvg.setName("dsChartAvg");
		dsChartAvg.setDock(ControlDock.FILL);
		tabPageChartData.add(dsChartAvg);

		dsChartRange = new DsChart();
		dsChartRange.setName("dsChartRange");
		dsChartRange.setDock(ControlDock.FILL);
		tabPageChartRange.add(dsChartRange);
	}

	@Override
	public Object ccomponentEventFired(CComponentEvent e)
	{
		Object source = e.getSource();
		String event = e.getEvent();

		if (DateTimePicker.VALUE_CHANGED.equals(event))
		{
			// if (dateTimePickerStart.equals(source) ||
			// dateTimePickerEnd.equals(source))
			// {
			// activityExecute();
			// }
		}
		if (FlatButton.CLICK.equals(event))
		{
			if (buttonQuery.equals(source))
			{
				activityExecute();
			}
		}
		return null;
	}

	private void setPoint(DsChart chart, Time time, float value)
	{
		if (value > chart.getYAxisMax())
		{
			chart.setYAxisMax(value);
		}
		if (value < chart.getYAxisMin())
		{
			chart.setYAxisMin(value);
		}
		long timeCurrent = time.getCalendar().getTimeInMillis();
		double xTimeCurrentValue = new Double(timeCurrent/(20*60*1000));
		chart.getDataset().addElement(
			xTimeCurrentValue, value, 4);
		chart.repaint();
	}

	@Override
	protected void startup()
	{
		super.startup();
		Time currentTime = getFunctions().getDBTime();
		dateTimePickerStart.setValue(currentTime.addHours(-4));
		dateTimePickerEnd.setValue(currentTime.addMinutes(30));

		dsChartRange.getXAxis().clearLabels();
		dsChartRange.getYAxis().clearLabels();
		dsChartAvg.getDataset().clear();
	}

	@Override
	public ItemDescriptor[] inputDescriptors()
	{
		ItemDescriptor[] descriptors = new ItemDescriptor[] {
			ItemDescriptor.createItemDescriptor(
				SPCChart.class, "partNumber", String.class, new Object[] {
					ItemDescriptor.SHORTDESCRIPTION, "The current partNumber." }),

			ItemDescriptor.createItemDescriptor(
				SPCChart.class, "dcsName", String.class, new Object[] {
					ItemDescriptor.SHORTDESCRIPTION, "The dcs name for the current step." }),

			ItemDescriptor.createItemDescriptor(
				SPCChart.class, "dcsItemName", String.class, new Object[] {
					ItemDescriptor.SHORTDESCRIPTION, "The dcs item name for the current step." }) };
		return descriptors;
	}

	@Override
	protected void inputItemSet(String arg0, Object arg1)
	{

	}

	@Override
	public Response activityExecute()
	{
		Response response = new Response();
		try
		{
			String partNumber = (String) getInputItem("partNumber");
			String dcsName = (String) getInputItem("dcsName");
			String dcsItemName = (String) getInputItem("dcsItemName");
			ATRowFilter atRowFilter = getFunctions().createATRowFilter(
				"BMSPCConfig");
			atRowFilter.forColumnNameContaining(
				"dcs_name", dcsName);
			atRowFilter.forColumnNameContaining(
				"dcs_item_name", dcsItemName);
			atRowFilter.forColumnNameContaining(
				"part_number", partNumber);
			Vector atRows = getFunctions().getFilteredATRows(
				atRowFilter, false);
			if (atRows != null && atRows.size() > 0)
			{
				ATRow atRow = (ATRow) atRows.get(0);
				float target = (Float) atRow.getValue("target");
				float upperBoundary = (Float) atRow.getValue("upper_boundary");
				float lowerBoundary = (Float) atRow.getValue("lower_boundary");
				float upperSpec = (Float) atRow.getValue("upper_spec");
				float lowerSpec = (Float) atRow.getValue("lower_spec");
				float upperControl = (Float) atRow.getValue("upper_control");
				float lowerControl = (Float) atRow.getValue("lower_control");
				dsChartAvg.getYAxis().clearLabels();
				dsChartRange.getYAxis().clearLabels();
				dsChartAvg.setYAxisLabel("X-Bar");
				dsChartAvg.setXAxisLabel("Time");
				dsChartAvg.getYAxis().addLabel(
					"3δ=" + lowerBoundary);
				dsChartAvg.getYAxis().addLabel(
					"2δ=" + lowerSpec);
				dsChartAvg.getYAxis().addLabel(
					"1δ=" + lowerControl);
				dsChartAvg.getYAxis().addLabel(
					"Target=" + target);
				dsChartAvg.getYAxis().addLabel(
					"-1δ=" + upperControl);
				dsChartAvg.getYAxis().addLabel(
					"-2δ=" + upperSpec);
				dsChartAvg.getYAxis().addLabel(
					"-3δ=" + upperBoundary);
				dsChartAvg.setYAxisMax(upperBoundary);
				dsChartAvg.setYAxisMin(lowerBoundary);
				dsChartAvg.getXAxis().clearLabels();

				float rangeTarget = (Float) atRow.getValue("range_target");
				float rangeMin = (Float) atRow.getValue("range_min");
				float rangeMax = (Float) atRow.getValue("range_max");
				dsChartRange.setYAxisLabel("Range");
				dsChartRange.getYAxis().addLabel(
					"UCL=" + rangeMin);
				dsChartRange.getYAxis().addLabel(
					"Target=" + rangeTarget);
				dsChartRange.getYAxis().addLabel(
					"LCL=" + rangeMax);
				dsChartRange.setYAxisMax(rangeMax);
				dsChartRange.setYAxisMin(rangeMin);
				dsChartRange.getXAxis().clearLabels();

				DCInstanceFilter dcInstanceFilter = getFunctions().createDCInstanceFilter(
					dcsName);
				Time startTime = dateTimePickerStart.getValue();
				Time endTime = dateTimePickerEnd.getValue();
				dcInstanceFilter.forCreatedTimeGreaterThanOrEqualTo(startTime);
				dcInstanceFilter.forCreatedTimeLessThan(endTime);
				dcInstanceFilter.forParmNotEqualTo(
					dcsItemName, null);
				// dcInstanceFilter.forPartNumberEqualTo(partNumber);
				dcInstanceFilter.addOrderBy(
					IDCSInstanceFilterAttributes.CREATIONTIME, IFilterSortOrders.ASCENDING);
				Vector spcData = getFunctions().getFilteredDCInstances(
					dcInstanceFilter);
				int size = spcData.size();
				if (size > 50)
				{
					throw new Exception("您查询的数据量超过了50条,请修改时间范围重新查询.");
				}
				dsChartAvg.getDataset().clear();
				dsChartRange.getDataset().clear();

				dsGridData.clearGrid();
				dsGridData.setNumberOfRows(5);
				dsGridData.setNumberOfColumns(size + 1);
				dsGridData.setCellText(
					0, 0, "Time");
				dsGridData.setCellText(
					1, 0, "Average");
				dsGridData.setCellText(
					2, 0, "R");
				dsGridData.setCellText(
					3, 0, "Point Value");
				dsGridData.setCellText(
					4, 0, "Cumnlative Score");

				Time minTime = getMinTime(spcData);
				Time maxTime = getMaxTime(spcData);
				long timeStart = minTime.getCalendar().getTimeInMillis();
				long timeEnd = maxTime.getCalendar().getTimeInMillis();
				dsChartAvg.setXAxisMin(new Double(timeStart/(20*60*1000)));
				dsChartAvg.setXAxisMax(new Double(timeEnd/(20*60*1000)));
				for(long begin = timeStart;begin<=timeEnd;begin+=(20*60*1000))
				{					
					Calendar c = Calendar.getInstance();
					c.setTimeInMillis(begin);					
					Time avgTime = new Time(c);
					String timeAvgText = avgTime.getHour() + ":" + avgTime.getMinute();
					dsChartAvg.getXAxis().addLabel(timeAvgText);
				}
//				dsChartAvg.setDrawLegend(false);
				
				dsChartRange.setXAxisMin(new Double(timeStart/(20*60*1000)));
				dsChartRange.setXAxisMax(new Double(timeEnd/(20*60*1000)));
				for(long begin = timeStart;begin<=timeEnd;begin+=(20*60*1000))
				{					
					Calendar c = Calendar.getInstance();
					c.setTimeInMillis(begin);					
					Time avgTime = new Time(c);
					String timeAvgText = avgTime.getHour() + ":" + avgTime.getMinute();
					dsChartRange.getXAxis().addLabel(timeAvgText);
				}
//				dsChartRange.setDrawLegend(false);
				double[] values = new double[size];
				for (int i = 0; i < size; i++)
				{
					DCInstance dcInstance = (DCInstance) spcData.get(i);
					Object objValue = dcInstance.getValue(dcsItemName);
					float value = 0.0f;
					if (objValue instanceof String)
					{
						value = Float.parseFloat((String) objValue);
					}
					else if (objValue instanceof Float)
					{
						value = (Float) objValue;
					}
					values[i] = value + 0.0;
					Time time = dcInstance.getCreationTime();
					String timeText = time.getHour() + ":" + time.getMinute();
					dsGridData.setCellText(
						0, i + 1, timeText);
					dsGridData.setCellText(
						1, i + 1, value);

					setPoint(
						dsChartAvg, time, value);
					int pointValue = 0;
					if (value >= lowerControl && value <= upperControl)
					{
						pointValue = 1;
					}
					else if ((value > upperControl && value <= upperSpec)
						|| (value >= lowerSpec && value < lowerControl))
					{
						pointValue = 2;
					}
					else if (value > upperSpec || value < lowerSpec)
					{
						pointValue = 4;
					}
					dsGridData.setCellValue(
						3, i + 1, pointValue);
					dsGridData.setCellValue(
						4, i + 1, pointValue);
					if (i > 0)
					{
						DCInstance dcInstanceLast = (DCInstance) spcData.get(i - 1);
						Object objLastValue = dcInstanceLast.getValue(dcsItemName);
						float lastValue = 0.0f;
						if (objValue instanceof String)
						{
							lastValue = Float.parseFloat((String) objLastValue);
						}
						else if (objValue instanceof Float)
						{
							lastValue = (Float) objLastValue;
						}

						float abs = new BigDecimal(Math.abs(lastValue - value)).setScale(
							2, BigDecimal.ROUND_UP).floatValue();
						dsGridData.setCellText(
							2, i + 1, abs);
						setPoint(
							dsChartRange, time, abs);
						int lastPointValue = Integer.parseInt(dsGridData.getCellText(
							3, i));
						if ((lastValue >= target && value <= target)
							|| (lastValue <= target && value >= target))
						{
							dsGridData.setCellValue(
								4, i + 1, 1);
						}
						else
						{
							int cumnlativeScore = lastPointValue + pointValue;
							int n = 4;
							if (cumnlativeScore >= 8)
							{
								// 塔灯亮红灯
								if (isAlert)
								{
									TestConnectQLight.writeRedLightOnOff();
								}
								dsChartAvg.getDataset().setPointColor(
									n, Color.red);
								dsGridData.setCellValue(
									4, i + 1, 1);
							}
							else
							{
								dsGridData.setCellValue(
									4, i + 1, cumnlativeScore);
								if (cumnlativeScore >= 5 && cumnlativeScore < 8)
								{
									// 塔灯亮黄灯
									if (isAlert)
									{
										TestConnectQLight.writeYellowLightOnOff();
									}
									dsChartAvg.getDataset().setPointColor(
										n, Color.yellow);
								}
								else if (cumnlativeScore >= 1 && cumnlativeScore <= 4)
								{
									// 塔灯亮绿灯
									if (isAlert)
									{
										TestConnectQLight.writeGreenLightOn();
									}
									dsChartAvg.getDataset().setPointColor(
										n, Color.green);
//									dsChartAvg.getDataset().setLineStyle(
//										n, DsStyle.LSNONE);
								}
							}
						}
					}

				}

				dsGridData.resizeColumnsToFit();
				dsChartAvg.invalidate();
				dsChartAvg.repaint();

				dsChartRange.invalidate();
				dsChartRange.repaint();

				int testCount = size;
				double avg = new BigDecimal(StdStats.mean(values)).setScale(
					2, BigDecimal.ROUND_UP).doubleValue();
				double max = new BigDecimal(StdStats.max(values)).setScale(
					2, BigDecimal.ROUND_UP).doubleValue();
				double min = new BigDecimal(StdStats.min(values)).setScale(
					2, BigDecimal.ROUND_UP).doubleValue();
				double deviation = new BigDecimal(StdStats.stddev(values)).setScale(
					2, BigDecimal.ROUND_UP).doubleValue();
				double ucl = new BigDecimal(avg + 3 * deviation).setScale(
					2, BigDecimal.ROUND_UP).doubleValue();
				double lcl = new BigDecimal(avg - 3 * deviation).setScale(
					2, BigDecimal.ROUND_UP).doubleValue();
				double cp1 = (max - avg) / (3 * deviation);
				double cp2 = (avg - min) / (3 * deviation);
				double cpk = new BigDecimal(cp1 > cp2 ? cp2 : cp1).setScale(
					2, BigDecimal.ROUND_UP).doubleValue();
				double higherRate = new BigDecimal(StdStats.highPercent(
					values, upperBoundary)).setScale(
					4, BigDecimal.ROUND_UP).doubleValue();
				String highPer = higherRate * 100 + "%";
				double lowerRate = new BigDecimal(StdStats.lowPercent(
					values, lowerBoundary)).setScale(
					4, BigDecimal.ROUND_UP).doubleValue();
				String lowPer = lowerRate * 100 + "%";

				dsGridAnalysis.setCellValue(
					0, 1, avg);
				dsGridAnalysis.setCellValue(
					1, 1, highPer);
				dsGridAnalysis.setCellValue(
					2, 1, lowPer);
				dsGridAnalysis.setCellValue(
					3, 1, cpk);
				dsGridAnalysis.setCellValue(
					4, 1, ucl);
				dsGridAnalysis.setCellValue(
					5, 1, lcl);
				dsGridAnalysis.setCellValue(
					6, 1, deviation);
				dsGridAnalysis.setCellValue(
					7, 1, testCount);
				dsGridAnalysis.setCellValue(
					8, 1, max);
				dsGridAnalysis.setCellValue(
					9, 1, min);

				dsGridAnalysis.resizeColumnsToFit();

			}
		}
		catch (Exception e)
		{
			response = createErrorResponse(e);
		}

		return response;
	}

	public Response executeDrawPoint(String partNumber, String dcsName, String dcsItemName,
		boolean isAlert)
	{
		setInputItem(
			"partNumber", partNumber);
		setInputItem(
			"dcsName", dcsName);
		setInputItem(
			"dcsItemName", dcsItemName);
		setAlert(isAlert);
		return activityExecute();
	}

	private Time getMinTime(Vector dcInstances)
	{
		Time tempMin = dateTimePickerEnd.getValue();
		for (int i = 0; i < dcInstances.size(); i++)
		{
			DCInstance dcInstance = (DCInstance) dcInstances.get(i);
			Time time = dcInstance.getCreationTime();
			if (time.compareTo(tempMin) == -1)
			{
				tempMin = time;
			}
		}
		return tempMin;

	}

	private Time getMaxTime(Vector dcInstances)
	{
		Time tempMax = dateTimePickerStart.getValue();
		for (int i = 0; i < dcInstances.size(); i++)
		{
			DCInstance dcInstance = (DCInstance) dcInstances.get(i);
			Time time = dcInstance.getCreationTime();
			if (time.compareTo(tempMax) == 1)
			{
				tempMax = time;
			}
		}
		return tempMax;

	}
}
